﻿using System;
using System.Reflection;
using System.Collections.Generic;
using System.Threading;
using System.Drawing;
using System.Windows.Forms;
using Xin478.CSWork.Common;
using Xin478.MySocket;


namespace Xin478.CSWork.Client
{
    public partial class MainForm : MyForm, IClient
    {
        #region 内部变量
        readonly static Type thisType = typeof(MainForm);

        bool isUserUnlink = false;//标示是否用户指示推出
        static object lockHelper = new object();
        TcpCli tcpCli;

        LoginForm loginForm;
        FileForm fileForm;
        NotifyIconHelper notifyHelper;

        TransferFileHelper transferFileHelper;
        #endregion

        #region 初始化

        public MainForm()
        {
            this.Visible = false;
            this.Load += new EventHandler(MainForm_Load);
            this.tcpCli = new TcpCli();
            this.tcpCli.DatagramAnalyze = new DatagramWorker();
            this.tcpCli.OnReceivedDatagramEvent += new NetEventHandler(instance_OnReceivedDatagramEvent);
            
        }

        void MainForm_Load(object sender, EventArgs e)
        {
            RequestAuthorize();

            if (!isUserUnlink)
                InitializeForm();
            else
            {
                this.tcpCli.Close();
                this.Dispose();
                Application.Exit();
            }
        }

        void RequestAuthorize()
        {
            this.CommandReceived += new CommandReceiveHandler(delegate(DatagramBuilder builder, ref bool cancel)
            {
                MethodInfo mi = thisType.GetMethod(builder.Name, BindingFlags.NonPublic | BindingFlags.IgnoreCase | BindingFlags.Instance);
                if (mi != null)
                {
                    mi.Invoke(this, builder.Params);
                    cancel = true;
                }
            });

            loginForm = new LoginForm();
            loginForm.提交事件 += new EventHandler(this.提交登录事件);
            this.tcpCli.OnConnectedServerEvent += new NetEventHandler(loginForm.LoginForm_OnConnected);
            this.tcpCli.OnDisConnectedServerEvent += new NetEventHandler( loginForm.LoginForm_OnUnConnected);
            this.tcpCli.OnSockErrorEvent+=new TcpCli.SockErrorEventHandler(mainForm_ReConnect);

            this.Connect();
            EmployeeInfo em = UserSession.Load();
            if(em!=null)
            {
                loginForm.用户名 = em.UserName;
                loginForm.密码 = em.PassWord;
                ThreadPool.QueueUserWorkItem(new WaitCallback(delegate{
                    int tryTime = 5;
                    WinForm.DoThreadSafe(this, delegate()
                    {
                        loginForm.锁定登录 = true; loginForm.状态 = "自动登录";
                    });
                    while (tryTime-- > 0)
                    {
                        if (this.tcpCli.IsConnected)
                        {
                            this.Send("User.Login", em.UserName, em.PassWord);
                            return;
                        }
                        Thread.Sleep(500);
                    }
                    MessageBox.Show("连接服务器失败");
                    WinForm.DoThreadSafe(this, delegate() { loginForm.锁定登录 = false; loginForm.状态 = "脱机"; });
                }));
            }

            if (loginForm.ShowDialog() != DialogResult.OK)
            {
                isUserUnlink = true; 
            }
        }

        void InitializeForm()
        {
            InitializeComponent();
            this.Icon = MainFormResource.Conntected;
            this.Closing += new System.ComponentModel.CancelEventHandler(this.关闭窗口事件);
            this.托盘图标.MouseMove += new MouseEventHandler(托盘图标_MouseMove);
            this.托盘图标.MouseClick += new MouseEventHandler(托盘图标_MouseClick);
            this.托盘图标.Icon = MainFormResource.Conntected;
            this.tcpCli.OnConnectedServerEvent += new NetEventHandler(建立连接事件);
            this.tcpCli.OnDisConnectedServerEvent += new NetEventHandler(断开连接事件);
            this.tcpCli.OnSockErrorEvent += new TcpCli.SockErrorEventHandler(连接服务器错误事件);
            this.notifyHelper = new NotifyIconHelper(this.托盘图标);

            #region 初始化传输
            this.transferFileHelper = new TransferFileHelper();
            this.transferFileHelper.MaxWorkingNum = 3;
            this.transferFileHelper.sendInvoke = new TransferFileHelper.SendInvoke(delegate(Session session, byte[] datagram) { this.Send(datagram); });
            this.DatagramReceived += new DatagramReceiveHandler(this.transferFileHelper.DatagramReceive);
            #endregion

            #region 初始化左侧菜单
            LeftMenuCtrl leftMenuCtrl = new LeftMenuCtrl();
            leftMenuCtrl.Name = "LeftMenuCtrl";
            leftMenuCtrl.Dock = DockStyle.Fill;
            leftPanel.Controls.Add(leftMenuCtrl);
            #endregion

            #region 初始化任务列表控件
            TaskMainCtrl taskMainCtrl = new TaskMainCtrl();
            taskMainCtrl.IClient = this;
            taskMainCtrl.Dock = DockStyle.Fill;
            taskMainCtrl.BindLeftMenu(leftMenuCtrl);
            myTabCtrl1.TabPages[0].Controls.Add(taskMainCtrl);
            //mainPanel.Controls.Add(taskMainCtrl);
            #endregion

            this.Visible = true;

            #region 预初始化提醒列表
            RemindListCtrl remindListCtrl = new RemindListCtrl();
            remindListCtrl.IClient = this;
            remindListCtrl.Dock = DockStyle.Fill;
            //mainPanel.Controls.Add(remindListCtrl);
            #endregion

            this.myHoverImg1.CheckedChanged += new EventHandler(myHoverImg1_CheckedChanged);
            this.myHoverImg2.CheckedChanged += new EventHandler(myHoverImg2_CheckedChanged);

        }

        /*
        void MainForm_InitAfterLogin()
        {
            RemindHelper.Instance.RemindTrigger += new EventHandler(RemindHelper_RemindTrigger);
            TipList.Instance.ItemAdded += new EventHandler(TipList_ItemAdded);
            TipList.Instance.ItemRemoved += new EventHandler(TipList_ItemRemoved);
        }
        void leftMenuCtrl_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e)
        {
            if (e.Node.Parent.Index < 2)
            {
                TaskMainCtrl taskMainCtrl = (TaskMainCtrl)mainPanel.Controls["TaskMainCtrl"];

                if (!taskMainCtrl.Visible)
                {
                    taskMainCtrl.Visible = true;
                    if (mainPanel.Controls.ContainsKey("RemindListCtrl"))
                    {
                        RemindListCtrl rc = mainPanel.Controls["RemindListCtrl"] as RemindListCtrl;
                        if (rc != null) rc.Sleep();
                    }
                }


                switch (e.Node.Parent.Index)
                {
                    case 0:
                        if (e.Node.Index == 0)
                            taskMainCtrl.ListShowMode = TaskMainCtrl.ListMode.MyProcessing;
                        else if (e.Node.Index == 1)
                            taskMainCtrl.ListShowMode = TaskMainCtrl.ListMode.MyFinished;

                        break;
                    case 1:
                        if (e.Node.Index == 0)
                            taskMainCtrl.ListShowMode = TaskMainCtrl.ListMode.SomeOneWaitAccept;
                        else if (e.Node.Index == 1)
                            taskMainCtrl.ListShowMode = TaskMainCtrl.ListMode.SomeOneProcessing;
                        else if (e.Node.Index == 2)
                            taskMainCtrl.ListShowMode = TaskMainCtrl.ListMode.SomeOneFinished;
                        break;
                }
            }
            else
            {
                mainPanel.Controls["TaskMainCtrl"].Visible = false;
                RemindListCtrl remindListCtrl=null;
                if (mainPanel.Controls.ContainsKey("RemindListCtrl"))
                {
                    remindListCtrl = (RemindListCtrl)mainPanel.Controls["RemindListCtrl"];
                }
                
                if(remindListCtrl==null)
                {
                    remindListCtrl = new RemindListCtrl();
                    remindListCtrl.IClient = this;
                    remindListCtrl.Name = "RemindListCtrl";
                    remindListCtrl.Dock = DockStyle.Fill;
                    mainPanel.Controls.Add(remindListCtrl);
                }

                switch (e.Node.Index)
                {
                    case 0:
                        remindListCtrl.ListDisplayType = RemindListCtrl.ListType.Schedule;
                        break;
                    case 1:
                        remindListCtrl.ListDisplayType = RemindListCtrl.ListType.NoHappen;
                        break;
                    case 2:
                        remindListCtrl.ListDisplayType = RemindListCtrl.ListType.Expire;
                        break;
                }
            }
        }      
        void RemindHelper_RemindTrigger(object sender, EventArgs e)
        {
            RemindInfo ri = sender as RemindInfo;
            WinForm.DoThreadSafe(this, delegate()
            {
                RemindTipItem remindTipItem = new RemindTipItem(ri, this.Send);
                TipList.Instance.Add(remindTipItem);
                
                //TipForm tf = new TipForm();
                //tf.Text = "到期提醒";
                //tf.ContentClick += new EventHandler(delegate(object _sender, EventArgs _e) { remindTipItem.ItemClick(remindTipItem); });
                //tf.Tag = ri;
                //tf.Message = ri.Detail;
                //tf.Show();
            });
        }
        void TipList_ItemRemoved(object sender, EventArgs e)
        {
            if (TipList.Instance.Count == 0) notifyHelper.NotifyStatus = tcpCli.IsConnected ? NotifyIconHelper.Status.Online : NotifyIconHelper.Status.Offline;
        }
        void TipList_ItemAdded(object sender, EventArgs e)
        {
            notifyHelper.NotifyStatus = NotifyIconHelper.Status.TwinkleNotice;
        }  
        */
        void myHoverImg1_CheckedChanged(object sender, EventArgs e)
        {
            MyHoverImg myImg = (MyHoverImg)sender;
            if (myImg.Checked)
            {                
                leftPanel.Controls["LeftMenuCtrl"].Visible = true;
            }
            myHoverImg2.Checked = !myImg.Checked;
        }

        void myHoverImg2_CheckedChanged(object sender, EventArgs e)
        {
            MyHoverImg myImg = (MyHoverImg)sender;
            if (myImg.Checked)
            {
                leftPanel.Controls["LeftMenuCtrl"].Visible = false;
                
            }
            myHoverImg1.Checked = !myImg.Checked;
        }

        void instance_OnReceivedDatagramEvent(object sender, NetEventArgs e)
        {
            bool cancel = false;
            if (DatagramReceived != null)
            {
                foreach (DatagramReceiveHandler handler in DatagramReceived.GetInvocationList())
                {
                    handler.Invoke(e.Client, ref cancel);
                    if (cancel) return;
                }
            }

            if (CommandReceived != null)
            {
                DatagramBuilder builder = DatagramBuilder.ToBuilder(e.Client.Datagram);
                builder.Params[0] = e;
                foreach (CommandReceiveHandler handler in CommandReceived.GetInvocationList())
                {
                    handler.Invoke(builder, ref cancel);
                    if (cancel) return;
                }
            }
        }

        void 建立连接事件(object obj, NetEventArgs e)
        {
            WinForm.DoThreadSafe(this, delegate()
            {
                this.notifyHelper.NotifyStatus= NotifyIconHelper.Status.Online;
                this.状态标签.Text = "联机";
                if (UserSession.Current != null) this.Send("用户登录", UserSession.Current.EmployeeInfo.UserName, UserSession.Current.EmployeeInfo.PassWord);
            });
        }

        void 断开连接事件(object obj, NetEventArgs e)
        {
            WinForm.DoThreadSafe(this, delegate()
            {
                this.notifyHelper.NotifyStatus = NotifyIconHelper.Status.Offline;
                this.状态标签.Text = "脱机";
                if (!this.isUserUnlink) { this.Connect(); }
            });
        }

        void mainForm_ReConnect(string errString)
        {
            WinForm.DoThreadSafe(this, delegate()
            {
                WinForm.DoThreadSafe(this, delegate() { this.Connect(); });
            });
        }

        void 连接服务器错误事件(string errString)
        {
            WinForm.DoThreadSafe(this, delegate() { this.状态标签.Text = "重新连接"; });
        }

        void 提交登录事件(object sender, EventArgs e)
        {
            if (loginForm == null) loginForm = new LoginForm();
            loginForm.锁定登录 = true;

            while (true)
            {
                if (this.tcpCli.IsConnected)
                {
                    this.Send("User.Login", loginForm.用户名, loginForm.密码);
                }
                else
                {
                    if (MessageBox.Show("无法连接服务器", "登陆失败", MessageBoxButtons.RetryCancel) == DialogResult.Retry)
                        continue;
                    else
                        loginForm.锁定登录 = false;
                }
                break;
            }

        }

        #endregion

        #region 辅助函数
        void Connect()
        {
            this.tcpCli.Connect(AppSettings.Default.服务器IP, AppSettings.Default.监听端口);
        }
        #endregion

        #region 窗体事件
        void 退出按钮_Click(object sender, EventArgs e)
        {
            this.退出程序事件();
        }

        void 托盘图标_MouseClick(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                托盘还原按钮_Click(sender, e);
            }
        }

        void 托盘图标_MouseMove(object sender, MouseEventArgs e)
        {
            if (TipList.Instance.Count > 0)
            {
                BoxForm.Display();
            }
        }

        void 托盘还原按钮_Click(object sender, EventArgs e)
        {
            if (this.WindowState == FormWindowState.Minimized || this.Visible == false)
            {
                this.Show();
            }
        }

        void 关闭窗口事件(object sender, System.ComponentModel.CancelEventArgs e)
        {
            this.Hide();
            e.Cancel = true;
        }

        void 退出程序事件() { this.退出程序(false); }

        void 退出程序(bool alwaysExit)
        {
            if (alwaysExit || MessageBox.Show("你确定要退出吗?", "退出", MessageBoxButtons.OKCancel) == DialogResult.OK)
            {
                lock (lockHelper) { isUserUnlink = true; }
                this.Send("User.Logout");
                this.CommandReceived = null;
                this.DatagramReceived = null;
                this.tcpCli.Close();
                //this.taskListCtrl1.Dispose();
                this.托盘图标.Visible = false;
                this.托盘图标.Dispose();
                this.Dispose();
                Application.Exit();
            }
        }

        void 传输图标按钮_ButtonClick(object sender, EventArgs e)
        {
            if (this.fileForm == null)
            {
                fileForm = new FileForm();
                fileForm.TransferFileHelper = transferFileHelper;
                fileForm.Disposed += new EventHandler(delegate(object _sender, EventArgs _e) { this.fileForm = null; });
                fileForm.Show();
            }
            else
            {
                if (fileForm.WindowState == FormWindowState.Minimized)
                {
                    fileForm.WindowState = FormWindowState.Normal;
                }
                else
                {
                    fileForm.Focus();
                }
            }
        }

        void 详细_提交完成按钮_Click(object sender, EventArgs e)
        {/*
            WorkInfo wi = this.任务详细.Tag as WorkInfo;
            if (wi == null) return;

            bool flag = !wi.IsFinished;
            if (flag && wi.WorkCommandInfos != null)
            {
                foreach (WorkCommandInfo cmd in wi.WorkCommandInfos) { if (!cmd.IsFinished)flag = false; break; }
            }
            if (!flag)
            {
                MessageBox.Show("该任务无法被提交，可能因为已标记完成或者有子任务未完成");
                return;
            }
            this.详细_提交完成按钮.Enabled = false;

            wi.FinishTime = DateTime.Now;
           // if (LocalMyWork.Update(MyWork.Works).AddColumn(MyWork.Works.FinishTime, wi.FinishTime).Where(MyWork.Works.Id==wi.Id).Execute() == 1)
           // {
                //this.发送("标记全部完成", wi.Id, wi.FinishTime);

            IList<TransferFileInfo> list = new List<TransferFileInfo>();
            
            foreach (ListViewItem item in this.详细_文件列表.Items)
            {
                if (item.Tag != null && (bool)item.Tag)
                {
                    TransferFileInfo fi = new TransferFileInfo();
                    fi.FileDir = item.Name.Substring(0, item.Name.LastIndexOf('\\') + 1);
                    fi.FileName = item.Name.Substring(item.Name.LastIndexOf('\\') + 1);
                    fi.Tag = wi.CustomerId.ToString();
                    list.Add(fi);

                    //this.发送文件(item.Name, wi.CustomerId);
                }
            }

            Thread thread = new Thread(new ParameterizedThreadStart(delegate
            {
                foreach(TransferFileInfo fi in list)
                    transferFileHelper.AddTransferFile(fi, null);
            }));
            thread.Priority = ThreadPriority.BelowNormal;
            thread.Start();
            this.fileForm.Show();
          //  }*/
        }
        #endregion

        #region 响应程序
        void 用户登录(NetEventArgs e, EmployeeInfo employeeInfo)
        {
            if (employeeInfo != null)
            { 
                try
                {
                    UserSession.NewSession(employeeInfo);
                }
                catch(Exception ex)
                {
                    MessageBox.Show(ex.Message);
                    this.退出程序(true);
                    return;
                }

                if (loginForm != null)
                {
                    UserSession.Current.EmployeeInfo.PassWord = loginForm.密码;
                    if(loginForm.自动登录) UserSession.Current.Save();

                    WinForm.DoThreadSafe(loginForm, delegate()
                    {
                        loginForm.登陆成功 = true;
                        loginForm.Close();
                        loginForm.Dispose();
                    });
                }

                //WinForm.DoThreadSafe(this,  delegate() { InitializeForm(); });
            }
            else
            {
                WinForm.DoThreadSafe(this, delegate()
                {
                    if (loginForm == null)
                    {
                        loginForm = new LoginForm();
                        loginForm.提交事件 += new EventHandler(this.提交登录事件);
                    }
                    this.loginForm.登陆失败();
                });
            }
        }
        void 用户资料(NetEventArgs e, EmployeeInfo employeeInfo)
        {
            /*
            if (Db.MyWork.Select(MyWork.Employees, MyWork.Employees.Id).Where(MyWork.Employees.Id == employeeInfo.Id).ToScalar() == null)
            {
                Db.MyWork.Insert(MyWork.Employees).AddColumn(MyWork.Employees.Id, employeeInfo.Id)
                    .AddColumn(MyWork.Employees.Name, employeeInfo.Name)
                    .AddColumn(MyWork.Employees.UserName, employeeInfo.UserName)
                    .Execute();
            }
            else
            {
                Db.MyWork.Update(MyWork.Employees)
                    .AddColumn(MyWork.Employees.Name, employeeInfo.Name)
                    .AddColumn(MyWork.Employees.UserName, employeeInfo.UserName)
                    .Where(MyWork.Employees.Id== employeeInfo.Id)
                    .Execute();
            }
             */ 
        }
        void 用户踢出(NetEventArgs e)
        {
            WinForm.DoThreadSafe(this, delegate() {
                MessageBox.Show("用户账号异地登陆或被服务器强行踢出");
                this.退出程序(true);
            });
        }
        void 提醒计划(NetEventArgs e, IList<RemindInfo> ris)
        {
            RemindHelper.Instance.Clear();
            RemindHelper.Instance.Add(ris);
            RemindHelper.Instance.Start();
        }
        #endregion

        #region IClient 成员

        public event CommandReceiveHandler CommandReceived;
        public event DatagramReceiveHandler DatagramReceived;

        public TransferFileHelper TransferFileHelper
        {
            get { return this.transferFileHelper; }
        }

        public bool Send(string command, params object[] fparams)
        {
            return this.Send(new DatagramBuilder(command, fparams).ToByte());
        }
        public bool Send(byte[] datagram)
        {
            bool sended = false;
            if (this.tcpCli.IsConnected)
            {
                try
                {
                    tcpCli.Send(datagram);
                    sended = true;
                }
                catch (System.Net.Sockets.SocketException socketexp)
                {
                    if (socketexp.ErrorCode == 10054)
                    {
                        this.Connect();
                    }
                }
                catch (ApplicationException apex)
                {
                    this.Connect();
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message);
                }
            }

            return sended;
        }
        public void AddTransferFile(string path, string tag)
        {
            transferFileHelper.AddTransferFile(path, tag, this.tcpCli.ClientSession);
        }
        public MyTabCtrl TabCtrl { get { return this.myTabCtrl1; } }

        #endregion
    }

    public delegate bool SendInvoke(string command, params object[] fparams);
}
